package srzy.socket

import java.net._
import java.util.concurrent.locks.ReentrantLock
import java.io.IOException
import srzy.common.Logging

abstract class SocketConn extends Logging {

  val socket: Socket
  val pro: Protocol
  val outStream: java.io.OutputStream
  val inStream: java.io.InputStream
  val readLock = new ReentrantLock()
  val writeLock = new ReentrantLock()

  def read(len: Int): Array[Byte] = {
    //    logger.debug("read in")
    val obj = new Array[Byte](len)
    var readed = 0
    var reading = 0
    var left = obj.length
    while (left > 0) {
      //      logger.debug("readed:" + readed + ", reading:" + reading + ", left:" + left)
      if (Thread.currentThread().isInterrupted()) {
        logger.debug("Thread is interrupted!")
        throw new InterruptedException()
      }
      //      try {
      reading = inStream.read(obj, readed, left)
      if (reading == -1) {
        throw new SocketClosedException()
      }
      readed += reading
      left -= reading
      //      } catch {
      //        case ste: SocketTimeoutException =>
      //        //          logger.debug("Socket read timeout")
      //      }
    }
    //    logger.debug("readed:" + readed + ", reading:" + reading + ", left:" + left)
    //    logger.debug("read done")
    return obj
  }

  def close() = {
    logger.info("Close SocketConn start!")
    try {
      socket.close()
      outStream.close()
      inStream.close()
    } catch {
      case e: Exception => logger.error("Close the connection failed !", e)
    }
    logger.info("Close SocketConn over!")
  }
}

object SocketConn extends Logging {

  def connect(serverIp: String, port: Int): Socket = {
    try {
      val s = new Socket()
      s.setSoLinger(true, 2)
      s.setSoTimeout(2000)
      s.setSendBufferSize(32 * 1024)
      s.setReceiveBufferSize(32 * 1024)
      s.setTcpNoDelay(true)
      s.connect(new InetSocketAddress(serverIp, port))
      logger.info("Established connection to " + serverIp + ":" + port
        + " connect success!")
      s
    } catch {
      case e: Exception =>
        logger.error("Established connection to " + serverIp + " : " + port
          + " connect failure!", e)
        throw e
    }
  }
}